#include <iostream>
#include <vector>
#include <memory>

using namespace std;
using TensorType = vector<float>;

class Variable{
public:
    Variable(const shared_ptr<TensorType>& data) {
        this->data = data;
    }

    shared_ptr<TensorType> data;
};

class Function {
public:
    Variable operator()(const Variable& input) {
        auto x = input.data;
        auto y = this->forward(x);

        return Variable(y);
    }

    virtual shared_ptr<TensorType> forward(const shared_ptr<TensorType>& in) = 0;

};

class Square : public Function {
public:
    shared_ptr<TensorType> forward(const shared_ptr<TensorType>& in) override {
        auto out = make_shared<TensorType>();
        for (auto e: *in) {
            out->push_back(e * e);
        }

        return out;
    }
};


int main() {
    auto data = make_shared<TensorType>(TensorType{1.1, 1.2});

    Variable x(data);
    Square f;
    auto y = f(x);

    cout << (*y.data)[0] << endl;
    cout << (*y.data)[1] << endl;

    return 0;
}